/**
 bind 函数的实现步骤：

1.判断调用对象是否为函数，即使我们是定义在函数的原型上的，但是可能出现使用 call 等方式调用的情况。
2.保存当前函数的引用，获取其余传入参数值。
3.创建一个函数返回
4.函数内部使用 apply 来绑定函数调用，需要判断函数作为构造函数的情况，这个时候需要传入当前函数的 this 给 apply 调用，
其余情况都传入指定的上下文对象。
*/

Function.prototype.myBind = function(context) {
    if(typeof this !== "function")
        throw new TypeError("Error");

    context = context || window;
    context.fn = this;

    /** 将第一个参数去除，剩余参数统一存放在数组中 */
    var args = [...arguments].slice(1);
7
    return function Fn() {
        var result = context.fn.apply(this instanceof Fn ? this : context, args.concat(...arguments));
        delete context.fn;
        return result;
    }
}

/** 测试 */
function fn1(a, b, c){
    console.log('this', this)
    console.log(a, b, c)
    return 'this is fn1'
  }

  const fn2 = fn1.myBind({x: 100, y: 200}, 10, 20, 30);
  const res = fn2();
  console.log(res) ;
